import os

from rest_framework.permissions import SAFE_METHODS, DjangoModelPermissions

ENV_IP_WHITE_LIST = 'IP_WHITE_LIST'


class WhiteListPermission(DjangoModelPermissions):
    """
    针对API层交互，添加Ip白名单权限。
    """
    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': [],
        'HEAD': [],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

    def is_in_white_list(self, request):
        """
        当前请求是否在白名单里。
        :param request:
        :return:
        """
        # 获取请求的ip地址，当部署的环境中有多层代理时，HTTP_X_FORWARDED_FOR里面会有多个值
        if request.META.get('HTTP_X_FORWARDED_FOR'):
            ip = request.META.get('HTTP_X_FORWARDED_FOR')
        else:
            ip = request.META.get('REMOTE_ADDR')
        if ip:
            # 第一个值便是客户端IP
            ip = ip.split(',')[0]

        ip_list_str = os.getenv(ENV_IP_WHITE_LIST)
        if ip_list_str:
            ip_list = ip_list_str.split(';')
            if ip in ip_list:
                return True
        return False

    def has_permission(self, request, view):
        """
        全局白名单权限类，当客户端的IP在白名单列表中时，并且请求方法为SAFE_METHODS中的一种，权限认证通过。
        除此之外，其他请求的权限都由Django的模型权限控制。
        :param request:
        :param view:
        :return:
        """
        if not request.auth:
            if self.is_in_white_list(request) and request.method in SAFE_METHODS:
                return True

        if hasattr(view, 'get_queryset'):

            return super().has_permission(request, view)
        else:
            return bool(request.user and request.user.is_authenticated)
